/*****************************************************************************************
 * File Name        : lock.h
 * Description      : 线程锁,守护者和条件变量的封装
 * Author           : chenht
 * History          : 
 * Date             : 20100522
 * Version          : 1.0
 * Modification : 
 ****************************************************************************************/
 
#ifndef __LOCK_H__
#define __LOCK_H__

#include <pthread.h>
#include "commhead.h"

/**
* 线程锁,利用构造和析构函数自动init和destroy
*/
class CLock
{
public:

    CLock(pthread_mutexattr_t* attrs = NULL)
    {
        int result = pthread_mutex_init(&m_mutex,attrs);
        if( result++ == EAGAIN){

        }
    }

    ~CLock()
    {
        pthread_mutex_destroy(&m_mutex);
    }

    //把m_mutex的地址拿出来给其他底层类使用,应用层一般不要调用这个函数
    pthread_mutex_t* GetKernel()
    {
        return &m_mutex;
    }

    //lock,If the mutex is already locked, the calling thread blocks until the mutex becomes available. 
    int Lock()
    {
        return pthread_mutex_lock(&m_mutex);
    }
  
    int UnLock()
    {
        return pthread_mutex_unlock(&m_mutex);
    }

    /*
    The pthread_mutex_timedlock() function shall lock the mutex object referenced by mutex. 
    If the mutex is already locked, the calling thread shall block until the mutex becomes available as in the pthread_mutex_lock()  function. 
    If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait shall be terminated when the specified timeout expires.
    */
    int Lock(const struct timespec* time)
    {
        return pthread_mutex_timedlock(&m_mutex,time);
    }

    //The function pthread_mutex_trylock() is identical to pthread_mutex_lock() except that if the mutex object referenced by mutex is currently locked (by any thread, including the current thread), the call returns immediately.
    int TryLock()
    {
        return pthread_mutex_trylock(&m_mutex);
    }

private:
    pthread_mutex_t m_mutex;
};


class CGuard
{
private:
    CLock* m_pLock;
    bool is_locked;

public:
    CGuard(CLock& lock):m_pLock(&lock)
    {		
        m_pLock->Lock();
        is_locked = true; //防止自己锁死自己
    }
    
    bool Lock(){

        if( is_locked ){
            return false;
        }

        m_pLock->Lock();
        is_locked = true;
        return true;
    }

    void UnLock()
    {
        m_pLock->UnLock();
    }

    ~CGuard(){
        UnLock();
    }		
};

///**
//* 条件变量
//* 使用方法参见同目录下的msgqueue.h
//* 每次调用wait or signal之前都用上面的CGuard收获住即可;或用Lock(),用完后UnLock()
//* 如此构造，先定义Lock m_lock;
//* 然后传给CCondition(m_lock);
//*/
//class CCondition
//{
//private:
//    // Condition variable.
//    pthread_cond_t _cond;
//    // 用来传给条件变量的函数
//    CLock *m_pLock;
//public:
//    //CCondition(CLock *pLock)  
//    CCondition(CLock& lock):m_pLock(&lock)
//    {
//        //m_pLock= pLock;
//        pthread_condattr_t attr;
//        pthread_condattr_init(&attr);
//		
//        if (pthread_cond_init (&this->_cond, &attr) != 0)
//        {
//            printf("call pthread_cond_init failed\n");
//        }
//        pthread_condattr_destroy(&attr);
//		                
//    }
//
//    ~CCondition(void)
//    {
//        if (this->remove() == -1)
//        {
//            printf("remove CCondition failed\n");
//        }
//    }
//
//    // Block on condition.
//    int wait(void)
//    {
//        return pthread_cond_wait(&this->_cond, m_pLock->GetKernel());
//    }
//	
//    // Block on condition.wait for a second time
//    int wait(const struct timespec* time)
//    {
//        return pthread_cond_timedwait (&this->_cond, m_pLock->GetKernel(), time);
//    }
//
//    // Signal one waiting thread.
//    int signal(void)
//    {
//        return pthread_cond_signal (&this->_cond);
//    }
//
//    // Signal *all* waiting threads.
//    int broadcast(void)
//    {
//        return pthread_cond_broadcast (&this->_cond);
//    }
//	
//    // Explicitly destroy the condition variable.
//    int remove(void)
//    {
//        int result = 0;
//        while ((result = pthread_cond_destroy (&this->_cond)) == -1 && errno == EBUSY)
//        {
//            pthread_cond_broadcast (&this->_cond);
//            Sleep(50);
//        }
//        return result;
//    }
//    
//};


#endif //__LOCK_H__


